aboutsummaryrefslogtreecommitdiff
path: root/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-24 13:09:50 +0000
committerFuwn <[email protected]>2026-01-24 13:09:50 +0000
commit396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch)
treeb9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
downloadumami-main.tar.xz
umami-main.zip
Initial commitHEADmain
Created from https://vercel.com/new
Diffstat (limited to 'src/app/(main)/websites/[websiteId]/WebsiteNav.tsx')
-rw-r--r--src/app/(main)/websites/[websiteId]/WebsiteNav.tsx180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
new file mode 100644
index 0000000..ad05b70
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
@@ -0,0 +1,180 @@
+import { Column, Text } from '@umami/react-zen';
+import { SideMenu } from '@/components/common/SideMenu';
+import { useMessages, useNavigation } from '@/components/hooks';
+import {
+ AlignEndHorizontal,
+ ChartPie,
+ Clock,
+ Eye,
+ Sheet,
+ Tag,
+ User,
+ UserPlus,
+} from '@/components/icons';
+import { WebsiteSelect } from '@/components/input/WebsiteSelect';
+import { Funnel, Lightning, Magnet, Money, Network, Path, Target } from '@/components/svg';
+
+export function WebsiteNav({
+ websiteId,
+ onItemClick,
+}: {
+ websiteId: string;
+ onItemClick?: () => void;
+}) {
+ const { formatMessage, labels } = useMessages();
+ const { pathname, renderUrl, teamId, router } = useNavigation();
+
+ const renderPath = (path: string) =>
+ renderUrl(`/websites/${websiteId}${path}`, {
+ event: undefined,
+ compare: undefined,
+ view: undefined,
+ });
+
+ const items = [
+ {
+ label: formatMessage(labels.traffic),
+ items: [
+ {
+ id: 'overview',
+ label: formatMessage(labels.overview),
+ icon: <Eye />,
+ path: renderPath(''),
+ },
+ {
+ id: 'events',
+ label: formatMessage(labels.events),
+ icon: <Lightning />,
+ path: renderPath('/events'),
+ },
+ {
+ id: 'sessions',
+ label: formatMessage(labels.sessions),
+ icon: <User />,
+ path: renderPath('/sessions'),
+ },
+ {
+ id: 'realtime',
+ label: formatMessage(labels.realtime),
+ icon: <Clock />,
+ path: renderPath('/realtime'),
+ },
+ {
+ id: 'compare',
+ label: formatMessage(labels.compare),
+ icon: <AlignEndHorizontal />,
+ path: renderPath('/compare'),
+ },
+ {
+ id: 'breakdown',
+ label: formatMessage(labels.breakdown),
+ icon: <Sheet />,
+ path: renderPath('/breakdown'),
+ },
+ ],
+ },
+ {
+ label: formatMessage(labels.behavior),
+ items: [
+ {
+ id: 'goals',
+ label: formatMessage(labels.goals),
+ icon: <Target />,
+ path: renderPath('/goals'),
+ },
+ {
+ id: 'funnel',
+ label: formatMessage(labels.funnels),
+ icon: <Funnel />,
+ path: renderPath('/funnels'),
+ },
+ {
+ id: 'journeys',
+ label: formatMessage(labels.journeys),
+ icon: <Path />,
+ path: renderPath('/journeys'),
+ },
+ {
+ id: 'retention',
+ label: formatMessage(labels.retention),
+ icon: <Magnet />,
+ path: renderPath('/retention'),
+ },
+ ],
+ },
+ {
+ label: formatMessage(labels.audience),
+ items: [
+ {
+ id: 'segments',
+ label: formatMessage(labels.segments),
+ icon: <ChartPie />,
+ path: renderPath('/segments'),
+ },
+ {
+ id: 'cohorts',
+ label: formatMessage(labels.cohorts),
+ icon: <UserPlus />,
+ path: renderPath('/cohorts'),
+ },
+ ],
+ },
+ {
+ label: formatMessage(labels.growth),
+ items: [
+ {
+ id: 'utm',
+ label: formatMessage(labels.utm),
+ icon: <Tag />,
+ path: renderPath('/utm'),
+ },
+ {
+ id: 'revenue',
+ label: formatMessage(labels.revenue),
+ icon: <Money />,
+ path: renderPath('/revenue'),
+ },
+ {
+ id: 'attribution',
+ label: formatMessage(labels.attribution),
+ icon: <Network />,
+ path: renderPath('/attribution'),
+ },
+ ],
+ },
+ ];
+
+ const handleChange = (value: string) => {
+ router.push(renderUrl(`/websites/${value}`));
+ };
+
+ const renderValue = (value: any) => {
+ return (
+ <Text truncate style={{ maxWidth: 160, lineHeight: 1 }}>
+ {value?.selectedItem?.name}
+ </Text>
+ );
+ };
+
+ const selectedKey = items
+ .flatMap(e => e.items)
+ .find(({ path }) => path && pathname.endsWith(path.split('?')[0]))?.id;
+
+ return (
+ <Column padding="3" position="sticky" top="0" gap>
+ <WebsiteSelect
+ websiteId={websiteId}
+ teamId={teamId}
+ onChange={handleChange}
+ renderValue={renderValue}
+ buttonProps={{ style: { outline: 'none' } }}
+ />
+ <SideMenu
+ items={items}
+ selectedKey={selectedKey}
+ allowMinimize={false}
+ onItemClick={onItemClick}
+ />
+ </Column>
+ );
+}